home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Mark Pilgrim / Fade Me 1.1 / source / sdf code ƒ / show init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-30  |  9.1 KB  |  332 lines  |  [TEXT/KAHL]

  1. /**********************************************************************\
  2.  
  3. File:        show init.c
  4.  
  5. Purpose:    This module handles actually putting the startup icon
  6.             on the screen at INIT loading time.
  7.             
  8. Note:        This file was not written by the author of Shutdown Fade
  9.             and is not subject to the licensing terms of the GNU General
  10.             Public License.
  11.  
  12.  
  13. Shutdown Fade -=- fade the screen to black on shutdown
  14. Copyright (C) 1993 Mark Pilgrim
  15.  
  16. This program is free software; you can redistribute it and/or modify
  17. it under the terms of the GNU General Public License as published by
  18. the Free Software Foundation; either version 2 of the License, or
  19. (at your option) any later version.
  20.  
  21. This program is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. GNU General Public License for more details.
  25.  
  26. You should have received a copy of the GNU General Public License
  27. along with this program in a file named "GNU General Public License".
  28. If not, write to the Free Software Foundation, 675 Mass Ave,
  29. Cambridge, MA 02139, USA.
  30.  
  31. \**********************************************************************/
  32.  
  33. #include "globals.h"
  34. #include "show init.h"
  35.  
  36. /* this file was received from Chris Tate - fixer@faxcsl.dcrt.nih.gov */
  37. /* it is modified - some typedefs have been moved to header files */
  38.  
  39. /*
  40.     ShowIconFamily.c
  41.     
  42.     ShowINIT compatible routine that shows 'ICN#' and 'iclx' flavor icons.
  43.     For use by all INITs in System 7 and beyond.
  44.     
  45.     by Patrick C. Beard.
  46.     
  47.     Instructions for use:
  48.     
  49.         % Create a family of icons with ResEdit 2.1 or later.  This will include
  50.          'ICN#', 'icl4', & 'icl8' icons.
  51.         % Use SetUpA4 to set up Think C globals.
  52.         % Call ShowIconFamily() with the resource id of the family that you used.
  53.     
  54.     Enhancements:
  55.         
  56.         % Uses 'iclx' & 'ICN#' icons from the Finder's "icon family" in System 7.
  57.         % Generates a position for icons that is guaranteed to be on screen, while
  58.           remaining compatible with previous releases of ShowInit.
  59.     
  60.     This code is completely public domain.  Let's hope this becomes a new standard.
  61.     
  62.     This code is derived from the original ShowInit by Paul Mercer, Darin Adler,
  63.     Paul Snively, and Steve Capps.
  64.     
  65.     Special thanks to Ben Haller & Rob Vaterlaus for valuable suggestions and help.
  66.  */
  67.  
  68. #include <OSUtils.h>
  69. #include <QuickDraw.h>
  70. /*#include <Color.h>*/
  71.  
  72. #ifndef nil
  73. #define nil ((void*)0)
  74. #endif
  75.  
  76. #ifndef topLeft
  77. #define topLeft(r) ((Point*)&r)[0])
  78. #endif
  79.  
  80. #ifndef botRight
  81. #define botRight(r) ((Point*)&r)[1])
  82. #endif
  83.  
  84. static short theDepth;                /* the depth the monitor is in. */
  85. static CGrafPtr port;
  86.  
  87. static void DrawBWIcon(short iconId);
  88. static void DrawColorIcon(short iconId);
  89.  
  90. /* this is where it all happens. */
  91.  
  92. void ShowIconFamily(short iconId)
  93. {
  94.     long oldA5;
  95.     QDGlobals qd;                /* our QD globals. */
  96.     SysEnvRec environment;        /* machine configuration. */
  97.     CGrafPort gp;                /* our grafport. */
  98.     
  99.     /* get a value for A5, a structure that mirrors qd globals. */
  100.     oldA5 = SetA5((long)&qd.end);
  101.     InitGraf(&qd.thePort);
  102.     
  103.     /* find out what kind of machine this is. */
  104.     SysEnvirons(curSysEnvVers, &environment);
  105.     if (environment.hasColorQD) {
  106.         theDepth = (**(**GetMainDevice()).gdPMap).pixelSize;
  107.         if (theDepth < 4)
  108.             theDepth = 1;
  109.     } else {
  110.         theDepth = 1;
  111.     }
  112.  
  113.     /* see what type of port to open. */
  114.     if (theDepth >= 4) {
  115.         OpenCPort(&gp);
  116.     } else {
  117.         OpenPort((GrafPtr)&gp);
  118.     }
  119.     port = &gp;
  120.     
  121.     if (theDepth == 1)
  122.         DrawBWIcon(iconId);
  123.     else
  124.         DrawColorIcon(iconId);
  125.     
  126.     SetA5(oldA5);
  127. }
  128.  
  129. /*
  130.     ShowInit's information is nestled at the tail end of CurApName.
  131.     It consists of a short which encodes the next horizontal offset,
  132.     and another short which is that value checksummed with the function below.
  133.  */
  134.  
  135. #define CurApName_LM    0x910
  136. #define ShowINITTable ((short*)(CurApName_LM + 32 - 4))
  137. #define CheckSumConst 0x1021        /* magic value to check-sum with. */
  138.  
  139. #define InitialXPosition 8            /* initial horizontal offset. */
  140. #define YOffset            40            /* constant from bottom to place the icon. */
  141. #define XOffset            40            /* amount to change it by. */
  142.  
  143. /* CheckSum() computes the magic value to determine if ShowInit's have run already. */
  144.  
  145. static short CheckSum(register short x)
  146. {
  147.     asm {
  148.         rol.w    #1, x
  149.     }
  150.     return (x ^ CheckSumConst);
  151. }
  152.  
  153. /*
  154.     GetIconRect() generates an appropriate rectangle to display the
  155.     next INIT's icon in.  It is also responsible for updating the horizontal
  156.     position in low memory.  This is a departure from the original ShowInit code,
  157.     which updates low memory AFTER displaying the icon.  This code won't generate
  158.     an icon position until it is certain that the icon can be loaded, so the
  159.     same behaviour occurs.
  160.     
  161.     This routine also generates a rectangle which is guaranteed to be onscreen.  It
  162.     does this by taking the horizontal offset modulo the screen width to generate
  163.     the horizontal position of the icon, and the offset divided by the screen
  164.     width to generate the proper row.
  165.  */
  166.  
  167. void GetIconRect(register Rect* iconRect)
  168. {
  169.     register short screenWidth = port->portRect.right - port->portRect.left;
  170.     /* if we are the first INIT to run we need to initialize the horizontal value. */
  171.     if (CheckSum(ShowINITTable[0]) != ShowINITTable[1])
  172.         ShowINITTable[0] = InitialXPosition;
  173.     
  174.     /* compute top left of icon's rect. */
  175.     iconRect->left = (ShowINITTable[0] % screenWidth);
  176.     iconRect->top = port->portRect.bottom - YOffset * (1 + (ShowINITTable[0] / screenWidth));
  177.     iconRect->right = iconRect->left + 32;
  178.     iconRect->bottom = iconRect->top + 32;
  179.     
  180.     /* advance the position for the next icon. */
  181.     ShowINITTable[0] += XOffset;
  182.     
  183.     /* recompute the checksum. */
  184.     ShowINITTable[1] = CheckSum(ShowINITTable[0]);
  185. }
  186.  
  187. /* DrawBWIcon() draws the 'ICN#' member of the icon family. */
  188.  
  189. void DrawBWIcon(short iconId)
  190. {
  191.     Handle icon;
  192.     Rect iconRect;
  193.     BitMap source, destination;
  194.     
  195.     icon = Get1Resource('ICN#', iconId);
  196.     if (!icon)
  197.         return;
  198.     HLock(icon);
  199.     
  200.     GetIconRect(&iconRect);
  201.  
  202.     /* prepare the source and destination bitmaps. */
  203.     source.baseAddr = *icon + 128;                    /* mask address. */
  204.     source.rowBytes = 4;
  205.     SetRect(&source.bounds, 0, 0, 32, 32);
  206.     destination = ((GrafPtr)port)->portBits;
  207.     
  208.     /* transfer the mask. */
  209.     CopyBits(&source, &destination, &source.bounds, &iconRect, srcBic, nil);
  210.     
  211.     /* and the icon. */
  212.     source.baseAddr = *icon;    
  213.     CopyBits(&source, &destination, &source.bounds, &iconRect, srcOr, nil);
  214.     
  215.     ReleaseResource(icon);
  216. }
  217.  
  218. /*
  219.     ChooseIcon() chooses the optimal icon for the current screen depth.
  220.     
  221.     Priorities for choosing icons:
  222.         1. match the bit depth to the icon.
  223.         2. use alternate bit depth version if available.
  224.         3. draw the black & white version.
  225.  */
  226.     
  227. Handle ChooseIcon(short iconId, short* suggestedDepth)
  228. {
  229.     short depth = *suggestedDepth;
  230.     Handle icon = nil;
  231.  
  232.     if (depth == 4) {
  233.         icon = Get1Resource('icl4', iconId);
  234.         if (!icon) {
  235.             /* try alternate depth. */
  236.             icon = Get1Resource('icl8', iconId);
  237.             if (icon)
  238.                 depth = 8;
  239.         }
  240.     } else {
  241.         depth = 8;
  242.         icon = Get1Resource('icl8', iconId);
  243.         if (!icon) {
  244.             /* try alternate depth. */
  245.             icon = Get1Resource('icl4', iconId);
  246.             if (icon)
  247.                 depth = 4;
  248.         }
  249.     }
  250.     
  251.     *suggestedDepth = depth;
  252.     return icon;
  253. }
  254.  
  255. /* DrawColorIcon() draws the appropriate icon for the current screen depth. */
  256.  
  257. void DrawColorIcon(short iconId)
  258. {
  259.     short depthToUse;
  260.     Handle mask, icon;
  261.     CTabHandle clut;
  262.     PixMapHandle source;
  263.     BitMap maskBits;
  264.     long rowBytes;
  265.     Rect iconRect, bounds;
  266.     
  267.     /* by default we will be using the actual depth of the screen. */
  268.     depthToUse = theDepth;
  269.     icon = ChooseIcon(iconId, &depthToUse);
  270.     
  271.     /* if no color icon available, draw the black & white icon. */
  272.     if (!icon) {
  273.         DrawBWIcon(iconId);
  274.         return;
  275.     }
  276.     HLock(icon);
  277.     
  278.     /* get the black & white icon to get the mask drawn. */
  279.     mask = Get1Resource('ICN#', iconId);
  280.     if (!mask)
  281.         return;
  282.     HLock(mask);
  283.  
  284.     /* get the correct color lookup table. */
  285.     clut = GetCTable(depthToUse);
  286.     if (!clut)
  287.         return;
  288.     
  289.     /* create a pixmap to stick the icon bits into for screen blitting. */
  290.     source = NewPixMap();
  291.     if (!source) {
  292.         DisposCTable(clut);
  293.         return;
  294.     }
  295.     
  296.     /* set up the source pixmap with the appropriate bounds, depth, and clut. */
  297.     bounds.top = bounds.left = 0;
  298.     bounds.bottom = bounds.right = 32;
  299.     rowBytes = (((depthToUse * 32) + 15) / 16) * 2;
  300.     (**source).baseAddr = *icon;
  301.     (**source).rowBytes = ((short)rowBytes) | 0x8000;
  302.     (**source).bounds = bounds;
  303.     (**source).pixelType = 0;            /* chunky model. */
  304.     (**source).pixelSize = depthToUse;
  305.     (**source).cmpCount = 1;            /* if in 32 bit mode this will be 3, so must change. */
  306.     (**source).cmpSize = depthToUse;    /* only chunky images used. */
  307.     DisposCTable((**source).pmTable);    /* dispose of default, uninitialized table. */
  308.     (**source).pmTable = clut;
  309.  
  310.     /* get position to draw icon in. */
  311.     GetIconRect(&iconRect);
  312.  
  313.     /* prepare the mask bitmap. */
  314.     maskBits.baseAddr = *mask + 128;                    /* mask address. */
  315.     maskBits.rowBytes = 4;
  316.     maskBits.bounds = bounds;
  317.  
  318.     /* punch out the mask. */    
  319.     CopyBits(&maskBits, &port->portPixMap, &bounds, &iconRect, srcBic, nil);
  320.     
  321.     /* draw the actual color icon. */
  322.     HLock((Handle)source);
  323.     CopyBits(*source, &port->portPixMap, &bounds, &iconRect, srcOr, nil);
  324.     
  325.     /* release everything we've allocated. */
  326.     (**source).baseAddr = nil;
  327.     DisposPixMap(source);
  328.     
  329.     /* release the icon and mask. */
  330.     ReleaseResource(icon);
  331.     ReleaseResource(mask);
  332. }